package cn.jjxx.shiro.session.config;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.jfree.util.Log;

import com.alibaba.fastjson.JSON;

import cn.jjxx.core.utils.StringUtils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.ScanParams;
import redis.clients.jedis.ScanResult;

/**
 * redis 操作类
 *@Title RedisUtil.java
 *@description TODO
 *@time 2020年7月16日 下午12:48:50
 *@author YAOXIONG
 *@version 1.0
 *
 */
public class RedisUtil {
	//Redis服务器IP
	private static String ADDR = PropertyUtils.getProperty("redis.host");

	//Redis的端口号
	private static String PORT =  PropertyUtils.getProperty("redis.port");

	//访问密码
	private static String AUTH = PropertyUtils.getProperty("redis.pass");

	//可用连接实例的最大数目，默认值为8；
	//如果赋值为-1，则表示不限制；如果pool已经分配了maxActive个jedis实例，则此时pool的状态为exhausted(耗尽)。
	//    private static int MAX_ACTIVE = 50;

	//控制一个pool最多有多少个状态为idle(空闲的)的jedis实例，默认值也是8。
	private static int MAX_IDLE = 200;

	//等待可用连接的最大时间，单位毫秒，默认值为-1，表示永不超时。如果超过等待时间，则直接抛出JedisConnectionException；
	private static int MAX_WAIT = 100000;

	private static int TIMEOUT = 100000;

	//在borrow一个jedis实例时，是否提前进行validate操作；如果为true，则得到的jedis实例均是可用的；
	private static boolean TEST_ON_BORROW = true;

	private static JedisPool jedisPool = null;

	/**
	 * 初始化Redis连接池
	 */
	static {
		try {
			JedisPoolConfig config = new JedisPoolConfig();
			config.setMaxIdle(MAX_IDLE);
			config.setMaxWaitMillis(MAX_WAIT);
			config.setTestOnBorrow(TEST_ON_BORROW);
			if(StringUtils.isEmpty(AUTH))
				AUTH=null;
			jedisPool = new JedisPool(config, ADDR,Integer.parseInt(PORT), TIMEOUT, AUTH);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 获取Jedis实例
	 * @return
	 */
	public synchronized static Jedis getJedis() {
		try {
			if (jedisPool != null) {
				Jedis resource = jedisPool.getResource();
				return resource;
			} else {
				return null;
			}
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 释放jedis资源
	 * @param jedis
	 */
	public static void returnResource(final Jedis jedis) {
		if (jedis != null) {
			jedisPool.returnResource(jedis);
		}
	}

	/**
	 * KEY对应value加1,并且设置过期时间
	 * @param db
	 * @param key
	 * @param ttl(s)
	 * @return
	 */
	public static long incrWithExpire(int db, String key, int ttl){
		Jedis resource=null;
		long res = 0;
		try {
			if (jedisPool != null) {
				resource = jedisPool.getResource();
				resource.select(db);
				res = resource.incr(key);
				if(res == 1){
					resource.expire(key, ttl);
				}

				jedisPool.returnResource(resource);
			}
			return res;
		} catch (Exception e) {
			e.printStackTrace();
			jedisPool.returnBrokenResource(resource);
			return 0;
		}
	}

	/**
	 * 删除set中多个fields
	 * @param db
	 * @param key
	 * @return
	 */
	public static long hdel(int db, String key, String[] fields){
		Jedis resource=null;
		long res = 0;
		try {
			if (jedisPool != null) {
				resource = jedisPool.getResource();
				resource.select(db);
				res = resource.hdel(key, fields);

				jedisPool.returnResource(resource);
			}
			return res;
		} catch (Exception e) {
			e.printStackTrace();
			jedisPool.returnBrokenResource(resource);
			return 0;
		}
	}
	/**
	 * 获取Redis里面的set里的值
	 * @param db
	 * @param key
	 * @param feild
	 * @return
	 */
	public static String hget(int db,String key,String feild){
		Jedis jedis = null;
		String value = null;
		try {
			if (jedisPool!=null) {
				jedis = jedisPool.getResource();
				jedis.select(db);
				value=jedis.hget(key,feild);
				jedisPool.returnResource(jedis);
			}
		}catch (Exception e){
			e.printStackTrace();;
			jedisPool.returnBrokenResource(jedis);
		}
		return value;
	}
	/**
	 * 写入Redis里面的set里的值
	 * @param db
	 * @param key
	 * @param feild
	 * @return
	 */
	public static void hset(int db,String key,String feild,String value){
		Jedis jedis = null;
		try{
			if(jedisPool!=null){
				jedis = jedisPool.getResource();
				jedis.select(db);
				jedis.hset(key,feild,value);
				jedisPool.returnResource(jedis);
			}
		}catch (Exception e){
			e.printStackTrace();
			jedisPool.returnBrokenResource(jedis);
		}
	}


	/**
	 * 迭代set里的元素
	 * @param db
	 * @param key
	 * @return
	 */
	public static ScanResult<Map.Entry<String,String>> hscan(int db, String key, String cursor, ScanParams scanParams){
		Jedis resource=null;
		ScanResult<Map.Entry<String,String>> scanResult = null;
		try {
			if (jedisPool != null) {
				resource = jedisPool.getResource();
				resource.select(db);
				scanResult = resource.hscan(key, cursor, scanParams);

				jedisPool.returnResource(resource);
			}
			return scanResult;
		} catch (Exception e) {
			e.printStackTrace();
			jedisPool.returnBrokenResource(resource);
			return scanResult;
		}
	}

	public static void main(String[] args) {
		System.out.println(incrWithExpire(0, "test", 10));
		ScanParams scanParams = new ScanParams();
		scanParams.count(10);
		Map<String, String> map = new HashMap<String, String>();
		System.out.println(JSON.toJSONString(hscan(2, "cuserMobileCabSet", "0", scanParams)));
	}


	/**
	 * 获取byte类型数据
	 * @param key
	 * @return
	 */
	public static byte[] getObject(int db,byte[] key,int expireTime){
		Jedis jedis = getJedis();
		byte[] bytes = null;
		if(jedis != null){
			jedis.select(db);
			try{
				bytes = jedis.get(key);
				if(null != bytes){
					jedis.expire(key,expireTime);
				}
			}catch(Exception e){
				e.printStackTrace();
			} finally{
				returnResource(jedis);
			}
		}
		return bytes;
	}

	/**
	 * 保存byte类型数据
	 * @param key
	 * @param value
	 */
	public static void setObject(int db,byte[] key, byte[] value,int expireTime){ 
		Jedis jedis = getJedis();
		if(jedis != null){
			jedis.select(db);
			try{  
				try { 
					jedis.del(key);
				} catch (Exception e) { 
				}
				jedis.set(key, value);
				// redis中session过期时间
				jedis.expire(key, expireTime);
			} catch(Exception e){
				e.printStackTrace(); 
			} finally{
				returnResource(jedis);
			}
		}
	}

	/**
	 * 更新byte类型的数据，主要更新过期时间
	 * @param key
	 */
	public static void updateObject(int db,byte[] key,byte[] value,int expireTime){
		Jedis jedis = getJedis();
		if(jedis != null){
			try{
				// redis中session过期时间
				jedis.select(db);
				jedis.set(key, value);
				jedis.expire(key, expireTime);
			}catch(Exception e){
				e.printStackTrace();
			} finally{
				returnResource(jedis);
			}
		}
	}

	/**
	 * 删除字符串数据
	 * @param key
	 */
	public static void delString(int db ,String key){
		Jedis jedis = getJedis();
		if(jedis != null){
			try{
				jedis.select(db);
				jedis.del(key);
			}catch(Exception e){
				e.printStackTrace();
			} finally{
				returnResource(jedis);
			}
		}
	}

	/**
	 * 存放字符串
	 * @param db
	 * @param key
	 * @param value
	 * @param expireTime
	 */
	public static void setString(int db,String key,String value,int expireTime){
		Jedis jedis = getJedis();
		if(jedis != null){
			jedis.select(db);
			try{
				jedis.set(key, value);
				// redis中session过期时间
				jedis.expire(key, expireTime);
			} catch(Exception e){
				e.printStackTrace();
			} finally{
				returnResource(jedis);
			}
		}
	}

	/**
	 * 获取字符串
	 * @param db
	 * @param key
	 * @param expireTime
	 * @return
	 */
	public static String getString(int db,String key,int expireTime){
		Jedis jedis = getJedis();
		String result = null;
		if(jedis != null){
			jedis.select(db);
			try{
				result = jedis.get(key);
				if(org.apache.commons.lang.StringUtils.isNotBlank(result)){
					jedis.expire(key,expireTime);
				}
			}catch(Exception e){
				e.printStackTrace();
			} finally{
				returnResource(jedis);
			}
		}
		return result;
	}

	/**
	 * 更新string类型的数据，主要更新过期时间
	 * @param key
	 */
	public static void updateString(int db,String key,String value,int expireTime){
		Jedis jedis = getJedis();
		if(jedis != null){
			try{
				// redis中session过期时间
				jedis.select(db);
				jedis.set(key, value);
				jedis.expire(key, expireTime);
			}catch(Exception e){
				e.printStackTrace();
			} finally{
				returnResource(jedis);
			}
		}
	}
	/**
	 * 更新string类型的数据，主要更新过期时间
	 * @param key
	 */
	public static void updateString(int db,String key,int expireTime){
		Jedis jedis = getJedis();
		if(jedis != null){
			try{
				// redis中token过期时间
				jedis.select(db);
				jedis.expire(key, expireTime);
			}catch(Exception e){
				e.printStackTrace();
			} finally{
				returnResource(jedis);
			}
		}
	}


	/**
	 * 模糊查询Redis中的KEY集合
	 *
	 * @param type  模糊查询的类型（PC,APP,INTERIOR）
	 * @param pattern 模糊查询的字符串 (门店ID，用户ID，角色ID)
	 * @param flag  库序号
	 * @return  返回值
	 */
	public static Set<String> keysLike(int db,String key) {
		Jedis jedis = getJedis(); 
		if(jedis != null){
			try{
				jedis.select(db); 
				//获取key集合
				Set<String> keys = jedis.keys(key);
				return keys;
			}catch(Exception e){
				e.printStackTrace();
			} finally{
				returnResource(jedis);
			}
		}
		return null;
	}  
	 
}
